﻿using HalconDotNet;
using Halcon二次开发.Controller.CamerForm交互;
using Halcon二次开发.Controller.Controller基类;
using Halcon二次开发.Controller.主界面交互;
using Halcon二次开发.Controller.多文本显示;
using Halcon二次开发.Controller.多模板匹配;
using Halcon二次开发.Controller.精准测量模块功能;
using Halcon二次开发.Controller.结果分析工具;
using Halcon二次开发.Controller.趋势图工具;
using Halcon二次开发.Controller.距离转换工具;
using Halcon二次开发.Model.储存每个Controller的单例对象;
using Halcon二次开发.Model.储放所有单例.储存每个单例界面;
using Halcon二次开发.Model.图像绑定流程图显示;
using Halcon二次开发.Tools;
using Halcon二次开发.View.中心距;
using Halcon二次开发.View.图片显示弹窗;
using Halcon二次开发.View.多模板匹配;
using Halcon二次开发.View.工位监控画面;
using Halcon二次开发.View.相机;
using Halcon二次开发.View.精准测量模块;
using Halcon二次开发.View.统计图;
using Halcon二次开发.View.角度界面;
using halcon联合.自定义控件;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Input;
using 可视化工具.Model.自定义控件;
using static System.Windows.Forms.AxHost;
using Image = System.Drawing.Image;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
using TreeNode = System.Windows.Forms.TreeNode;
using TreeNodeCollection = System.Windows.Forms.TreeNodeCollection;

namespace Halcon二次开发.Model.自定义控件
{
    public partial class HwindowFlowNodeUrseControl : UserControl
    {
        public Dictionary<string, int> ngDictionary = new Dictionary<string, int>();
        //监控画面的窗口对象
        public FramesTimeForm framesTimeForm;
        /// <summary>
        ///  ok个数集合
        /// </summary>
        public int okCount = 0;
        /// <summary>
        /// ng个数集合
        /// </summary>
        public int ngCount = 0;
        /// <summary>
        /// 运行按钮点击次数 计数器
        /// </summary>
        int runCount = 0;
        /// <summary>
        /// 这个板块的所有小窗体
        /// </summary>
        public List<Form> forms = new List<Form>();
        //当前任务名字
        public string name;
        //当前工程名字
        public string projectName;
        /// <summary>
        /// 当前显示的图像(需要一直获取)
        /// </summary>
        public HObject hImage;

        public Form1Controller form1Controller;
        /// <summary>
        /// 图像索引
        /// </summary>
        public int count;

        /// <summary>
        /// 鼠标右击选择输入输出的子节点对象
        /// </summary>
        public TreeNode mouseNode;
        /// <summary>
        /// 鼠标出现在节点上方获取的节点对象
        /// </summary>
        public TreeNode msMoveNode;
        //当前工位相机对象
        public CamerFormController camerFormController;
        public HwindowFlowNodeUrseControl()
        {
            try
            {
                InitializeComponent();
                //取消线程之间的访问
                CheckForIllegalCrossThreadCalls = false;
                //给HSmart绑定缩放事件
                hSmartWindowControl1.MouseWheel += HSmartWindowControl1_MouseWheel;
                foreach (Image item in ((Form1)FormDb.Db["Form1"]).imageList1.Images)
                {
                    imageList1.Images.Add(item);
                }
                treeView1.SelectedImageIndex = 149;
                customBarChartControl1.Data = ngDictionary;


            }
            catch
            {
                
            }

        }
        public new void Refresh()
        {
            try
            {

                customBarChartControl1.Data = ngDictionary;
                framesTimeForm.customBarChartControl1.Data = ngDictionary;
            }
            catch
            {
                
            }
        }

        public void HSmartWindowControl1_MouseWheel(object sender, MouseEventArgs e)
        {
            try
            {

                hSmartWindowControl1.HSmartWindowControl_MouseWheel(sender, e);
            }
            catch
            {

            }
        }

        /// <summary>
        /// 开始拖拽
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            //DoDragDrop(e.Item, DragDropEffects.Move);
        }
        /// <summary>
        /// 拖入工作区   
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_DragEnter(object sender, DragEventArgs e)
        {
            try
            {

                e.Effect = DragDropEffects.Move;
            }
            catch
            {

            }
        }
        /// <summary>
        /// 拖放完成时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                //终点节点坐标
                Point dropPoint = treeView1.PointToClient(new Point(e.X, e.Y));
                //终点节点
                TreeNode targetNode = treeView1.GetNodeAt(dropPoint);

                if (targetNode == null)
                {
                    // 拖拽到TreeView的空白区域，可以根据需要处理  
                    return;
                }
                //当前节点
                TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
                //
                if (draggedNode.Parent != null)
                {
                    return;
                }
                // 防止节点移动到其子节点或自己内部  
                if (draggedNode.Parent == targetNode)
                {
                    return;
                }

                //判断头部
                if (targetNode.Index == 0 && targetNode.Parent == null)
                {
                    draggedNode.Remove();
                    treeView1.Nodes.Insert(0, draggedNode);
                    //末尾节点
                }
                else if (targetNode.Index == treeView1.Nodes.Count - 1 && targetNode.Parent == null)
                {
                    draggedNode.Remove();
                    treeView1.Nodes.Add(draggedNode);
                }
                else
                {
                    // 移动节点  
                    if (targetNode.Parent == null && draggedNode.Parent == null)
                    {
                        int index = treeView1.Nodes.IndexOf(targetNode);
                        // 拖拽到根节点  
                        draggedNode.Remove();
                        treeView1.Nodes.Insert(index, draggedNode);
                    }
                    else
                    {
                        //判断是不是子节点,必须要两个节点都没有父节点
                        if (draggedNode.Parent != null && targetNode.Parent != null)
                        {
                            Graphics gh = treeView1.CreateGraphics();
                            Pen pen = new Pen(Color.Red);

                            gh.DrawLine(pen, dropPoint, new Point(200));
                        }
                        return;
                    }
                }
                // 可选：确保拖动的节点是可见的  
                treeView1.SelectedNode = draggedNode;
                if (targetNode != null)
                {
                    DisconnectLink(targetNode);
                }
                if (draggedNode != null)
                {
                    DisconnectLink(draggedNode);
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 拖放完成后 断开不正确的连接
        /// </summary>
        private void DisconnectLink(TreeNode node)
        {
            try
            {
                int index = treeView1.Nodes.IndexOf(node);
                TreeNodeCollection childNodes = node.Nodes;
                foreach (TreeNode childNode in childNodes)
                {
                    if (!childNode.Text.Contains("<—")) continue;
                    string[] values = childNode.Text.Split(new char[] { '—', '<', '.' }, StringSplitOptions.RemoveEmptyEntries);
                    bool paper = true;
                    for (int i = 0; i < index; i++)
                    {
                        if (treeView1.Nodes[i].Text == values[1])
                        {
                            paper = false;
                        }
                    }
                    if (paper)
                    {
                        childNode.Text = childNode.Name;
                        childNode.ForeColor = Color.Black;
                    }
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 双击打开页面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            try
            {

                form1Controller.ShowForm(e.Node.Tag);
            }
            catch
            {

            }
        }

        /// <summary>
        /// 运行(下一张图片)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void toolStripButton1_Click(object sender, EventArgs e)
        {
            try
            {
                Stopwatch runTime = new Stopwatch();
                runTime.Start();
                //是否执行结果分析
                //结果分析工具帮助集合
                Dictionary<List<bool>, string> resultHelper = new Dictionary<List<bool>, string>();

                Stopwatch stopwatch = new Stopwatch();
                string noweDate = DateTime.Now.ToString("MM:dd:HH:mm:ss");
                runCount++;
                (FormDb.Db["Form1"] as Form1).textBox1.AppendText("当前工位：" + this.name + " 运行次数：" + runCount + " \r\n");
                if (treeView1.Nodes == null || treeView1.Nodes.Count == 0) return;
                //获取相机的图片
                HObject camerImage = null;
                TreeNode camerNode = treeView1.Nodes[0];
                CamerFormController camerObj = camerNode.Tag.GetType().GetField("controller").GetValue(camerNode.Tag) as CamerFormController;
                //更新图像到本句柄中(要本相机类型的)

                //执行模板匹配 获取模板的数据
                double[] HideOutputArrayRows = new double[0];
                double[] HideOutputArrayColumns = new double[0];
                double[] HideOutputArrayPhis = new double[0];
                try
                {
                    stopwatch.Start();
                    camerObj.Run();
                    stopwatch.Stop();
                    camerImage = camerObj.HideOutputImage;
                    this.hImage = camerImage;  //给当前图像,后续进行图像保存
                    HOperatorSet.ClearWindow(hSmartWindowControl1.HalconWindow);
                    HOperatorSet.DispObj(camerImage, hSmartWindowControl1.HalconWindow);
                    //图像居中
                    hSmartWindowControl1.SetFullImagePart();
                    camerNode.ForeColor = Color.Black;

                    (FormDb.Db["Form1"] as Form1).textBox1.AppendText("当前时间：" + noweDate + "     " + treeView1.Nodes[0].Text + "运行成功 ！     执行时间:" + stopwatch.ElapsedMilliseconds.ToString() + "ms\r\n");
                    treeView1.Nodes[0].ForeColor = Color.Black;

                    int PmaPaper = -1;
                    //要判断有没有PMA工具
                    for (int i = 0; i < treeView1.Nodes.Count; i++)
                    {
                        if (treeView1.Nodes[i].Text.Contains("多目标"))
                        {
                            PmaPaper = i;
                        }
                    }
                    if (PmaPaper != -1)
                    {
                        TreeNode pmaNode = treeView1.Nodes[PmaPaper];
                        H_PMA_S_AlignToolForm pma = (pmaNode.Tag as H_PMA_S_AlignToolForm);
                        Shap_S_Matching model = (pmaNode.Tag.GetType().GetField("controller").GetValue(pmaNode.Tag) as Shap_S_Matching);
                        //设置图像
                        model.HideIntputImage = camerImage;
                        stopwatch.Start();
                        model.Run();
                        stopwatch.Stop();
                        ShowOk<double>(noweDate, pmaNode.Name, model.HideOutputArrayScores, stopwatch.ElapsedMilliseconds.ToString());
                        pmaNode.ForeColor = Color.Black;
                        HideOutputArrayRows = model.HideOutputArrayRows;
                        HideOutputArrayColumns = model.HideOutputArrayColumns;
                        HideOutputArrayPhis = model.HideOutputArrayPhis;
                    }
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null)
                    {
                        (FormDb.Db["Form1"] as Form1).textBox1.AppendText(camerNode.Name + ":" + ex.InnerException.Message + "  " + noweDate + "\r\n");
                        camerNode.ForeColor = Color.Red;
                    }
                    else
                    {
                        (FormDb.Db["Form1"] as Form1).textBox1.AppendText(camerNode.Name + ":" + ex.Message + "  " + noweDate + "\r\n");
                        camerNode.ForeColor = Color.Red;
                    }

                }

                //获取模板匹配控件的对象以及值
                //不是相机类型
                for (int i = 0; i < treeView1.Nodes.Count; i++)
                {
                    TreeNode item = treeView1.Nodes[i];
                    FieldInfo controller = item.Tag.GetType().GetField("controller");
                    if (controller == null) continue;
                    MethodInfo run = controller.GetValue(item.Tag).GetType().GetMethod("Run");
                    if (run == null) continue;
                    //百分率
                    try
                    {
                        if (item.Text.Contains("找圆") || item.Text.Contains("找线"))
                        {
                            //动作对象
                            object control = item.Tag.GetType().GetField("controller").GetValue(item.Tag);
                            //设置图像
                            control.GetType().GetField("HideIntputImage").SetValue(control, camerImage);
                            //设置行数组
                            control.GetType().GetField("HideIntputArrayRows").SetValue(control, HideOutputArrayRows);
                            //设置列数组
                            control.GetType().GetField("HideIntputArrayColumns").SetValue(control, HideOutputArrayColumns);
                            //设置角度数组
                            control.GetType().GetField("HideIntputArrayPhis").SetValue(control, HideOutputArrayPhis);
                            stopwatch.Start();
                            run.Invoke(controller.GetValue(item.Tag), null);
                            stopwatch.Stop();
                            item.ForeColor = Color.Black;
                            //设置角度数组
                            double[] result = control.GetType().GetField("HideOutputArrayDistances").GetValue(control) as double[];


                            ShowOk<double>(noweDate, item.Name, result, stopwatch.ElapsedMilliseconds.ToString());
                        }

                        else if (item.Text.Contains("测量模块"))
                        {

                            CaliperModuleController modelController = (item.Tag.GetType().GetField("controller").GetValue(item.Tag) as CaliperModuleController);
                            modelController.HideIntputImage = camerImage;
                            modelController.HideIntputArrayRows = HideOutputArrayRows;
                            modelController.HideIntputArrayColumns = HideOutputArrayColumns;
                            modelController.HideIntputArrayPhis = HideOutputArrayPhis;
                            stopwatch.Start();
                            modelController.Run();
                            stopwatch.Stop();
                            //获取距离转换工具输出的结果
                            double[] values = (item.Tag as CaliperModuleForm).distanceForm.controller.HideOutputArrayDistances;
                            ShowOk<double>(noweDate, item.Name, values, stopwatch.ElapsedMilliseconds.ToString());

                            //将结果分析工具产生的结果收集
                            if ((item.Tag as CaliperModuleForm).analyseForm.comboBox1.Text == "打开")
                            {
                                resultHelper.Add((item.Tag as CaliperModuleForm).analyseForm.controller.HideOutputResults, item.Name);
                            }
                            //将角度工具产生的结果收集
                            if ((item.Tag as CaliperModuleForm).anagleForm.comboBox1.Text.Trim() == "打开")
                            {
                                resultHelper.Add((item.Tag as CaliperModuleForm).anagleForm.controller.HideOutputResults, item.Name);
                            } //将间距工具产生的结果收集
                            if ((item.Tag as CaliperModuleForm).distansceForm.comboBox1.Text.Trim() == "打开")
                            {
                                resultHelper.Add((item.Tag as CaliperModuleForm).distansceForm.controller.HideOutputResults, item.Name);
                            }
                            item.ForeColor = Color.Black;
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex.InnerException != null)
                        {
                            (FormDb.Db["Form1"] as Form1).textBox1.AppendText("当前时间：" + noweDate + "     " + item.Name + ":" + ex.InnerException.Message + "\r\n");
                            this.Invoke((MethodInvoker)delegate
                            {
                                NgMessage form = NgMessage.GetSingle(item.Name + "运行错误! 流程中断:  " + ex.InnerException.Message);
                                form.Show();
                            });
                        }
                        else
                        {
                            (FormDb.Db["Form1"] as Form1).textBox1.AppendText("当前时间：" + noweDate + "     " + item.Name + "运行错误！\r\n");
                            this.Invoke((MethodInvoker)delegate
                            {
                                NgMessage form = NgMessage.GetSingle(item.Name + "运行错误! 流程中断:  " + ex.Message);
                                form.Show();
                            });
                        }
                        item.ForeColor = Color.Red;
                        break;
                    }
                    finally
                    {
                        try
                        {
                            //实时监控图像
                            if (framesTimeForm != null)
                            {

                                HOperatorSet.DumpWindowImage(out HObject image, hSmartWindowControl1.HalconWindow);
                                HOperatorSet.DispObj(image, framesTimeForm.Hwindow.HalconWindow);
                                framesTimeForm.Hwindow.SetFullImagePart();
                                //将数据显示到界面上
                                try
                                {
                                    framesTimeForm.sumLabel.Text = (okCount + ngCount).ToString();
                                    framesTimeForm.okLabel.Text = okCount.ToString();
                                    framesTimeForm.ngLabel.Text = ngCount.ToString();
                                    double number = okCount / (okCount + ngCount) * 100;
                                    framesTimeForm.okLabelRate.Text = number + "%";
                                    framesTimeForm.ngLabelRate.Text = 100 - number + "%";
                                }
                                catch { }
                            }

                        }
                        catch
                        {

                        }
                    }

                }

                runTime.Stop();
            }
            catch
            {

            }
           
        }
        /// <summary>
        /// 结果分析工具
        /// </summary>
        public void ToolAnalysis(Dictionary<List<bool>, string> resultHelper, HObject camerHObject)
        {
            try
            {
                if (resultHelper == null || resultHelper.Count == 0) return;

                bool hasNgPaper = false;
                string defectName = string.Empty;

                // 分析结果，找到首个不良项
                foreach (var item in resultHelper)
                {
                    if (item.Key.Any(v => !v)) // 如果有NG的标志
                    {
                        hasNgPaper = true;
                        defectName = item.Value;
                        break; // 发现不良直接退出
                    }
                }

                // 执行相应的处理
                if (hasNgPaper)
                {
                    if (treeView1.Nodes.Count > 0)
                    {
                        // 判断当前工位是否有相机工具
                        camerFormController = (treeView1.Nodes[0].Tag as CamerForm)?.controller;
                    }

                    camerFormController?.LevelReversal(); // 输出电平信号

                    ShowNgForm(camerHObject);            // 显示不良图像
                    WriteImage(camerHObject, false, defectName); // 保存不良图像
                    runPaper = false;                    // 设置状态
                }
                else
                {
                    WriteImage(camerHObject, true, string.Empty); // 保存良品图像
                }
            }
            catch
            {

            }
        }
        private long _lastWriteImageTicks = 0; // 使用Ticks记录上次调用时间
        /// <summary>
        /// 将合格和不合格的写入文件
        /// </summary>
        /// <param name="hObject"></param>
        /// <param name="result"></param>
        /// <param name="name"></param>
        public void WriteImage(HObject hObject, bool result, string name)
        {
            try
            {
                long nowTicks = DateTime.Now.Ticks;

                // 执行原有逻辑
                string ngPath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\NG\\";
                string okPath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\";
                if (!Directory.Exists(ngPath))
                {
                    Directory.CreateDirectory(ngPath);
                }
                if (!Directory.Exists(okPath))
                {
                    Directory.CreateDirectory(okPath);
                }
                if (result)
                {
                    okCount++;
                }
                else
                {
                    // 检查距离上次调用是否超过1秒
                    if (nowTicks - Interlocked.Read(ref _lastWriteImageTicks) < TimeSpan.TicksPerSecond)
                    {
                        return; // 如果不到1秒，直接返回
                    }
                    // 更新上次调用时间
                    Interlocked.Exchange(ref _lastWriteImageTicks, nowTicks);
                    string time = DateTime.Now.ToString("MM月dd日HH时mm分ss秒fff毫秒");
                    string ng = ngPath + $"{ngCount}_{time}_{name}.png";
                    HOperatorSet.WriteImage(hObject, "png", 0, ng);
                    ngCount++;
                    if (ngDictionary.ContainsKey(name))
                    {
                        ngDictionary[name] = 1 + ngDictionary[name]; // 如果键存在，增加值
                    }
                    else
                    {
                        ngDictionary.Add(name, 1); // 如果键不存在，添加键并赋值
                    }
                    this.Refresh();

                    string ngCountFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\ng分析.dat";
                    HelpJsons.SerializeKeyValuePairs(ngDictionary, ngCountFilePath);

                    this.timer2.Enabled = false;
                    this.timer3.Enabled = false;
                    this.timer5.Enabled = false;
                    if (this.InvokeRequired)
                    {
                        // 如果当前线程不是 UI 线程，使用 BeginInvoke 转到 UI 线程执行
                        this.BeginInvoke((Action)(() =>
                        {
                            // 启动闪烁
                            framesTimeForm.indicatorLight1.State = IndicatorLight.IndicatorState.RedBlinking; // 切换为红色闪烁   
                        }));
                    }
                }
            }
            catch (Exception ex) { }
           
        }
        private long _lastNgFormShowTicks = 0; // 使用Ticks记录时间
        /// <summary>
        /// 展示ng图片
        /// </summary>
        /// <param name="image"></param>
        public void ShowNgForm(HObject image)
        {
            try
            {
                long nowTicks = DateTime.Now.Ticks;
                if (nowTicks - Interlocked.Read(ref _lastNgFormShowTicks) < TimeSpan.TicksPerSecond)
                {
                    return; // 如果不到1秒，直接返回
                }
                Interlocked.Exchange(ref _lastNgFormShowTicks, nowTicks);

                this.Invoke((MethodInvoker)delegate
                {
                    ImageNgForm form = ImageNgForm.GetSingle().DispImage(image);
                    form.StartPosition = FormStartPosition.CenterParent;
                    form.BringToFront();
                    form.Focus();
                    form.Show();
                });
            }
            catch
            {

            }
        }
        public void ShowResults(string[] strs, HSmartWindowControl hSmartWindowControls)
        {
            try
            {
                for (int i = 0; i < strs.Length; i++)
                {
                    if (i == 0)
                    {
                        //设置文本显示的坐标
                        HOperatorSet.SetTposition(hSmartWindowControls.HalconWindow, 30, 40 + i * 200);
                        //设置字体
                        HOperatorSet.SetFont(hSmartWindowControls.HalconWindow, "宋体" + "-Normal-" + 20);

                        //设置颜色
                        HOperatorSet.SetColor(hSmartWindowControls.HalconWindow, "black");
                        //设置文字
                        HOperatorSet.WriteString(hSmartWindowControls.HalconWindow, strs[i]);
                    }
                    else if (i == 1 || i == 2)
                    {
                        //设置文本显示的坐标
                        HOperatorSet.SetTposition(hSmartWindowControls.HalconWindow, 30, 70 + i * 200);
                        //设置字体
                        HOperatorSet.SetFont(hSmartWindowControls.HalconWindow, "宋体" + "-Normal-" + 20);

                        //设置颜色
                        if (i == 1)
                        {

                            HOperatorSet.SetColor(hSmartWindowControls.HalconWindow, "green");
                        }
                        else if (i == 2)
                        {

                            HOperatorSet.SetColor(hSmartWindowControls.HalconWindow, "red");
                        }
                        //设置文字
                        HOperatorSet.WriteString(hSmartWindowControls.HalconWindow, strs[i]);
                    }
                    else if (i == 3)
                    {
                        //设置文本显示的坐标
                        HOperatorSet.SetTposition(hSmartWindowControls.HalconWindow, 30, 70 + i * 230);
                        //设置字体
                        HOperatorSet.SetFont(hSmartWindowControls.HalconWindow, "宋体" + "-Normal-" + 20);

                        //设置颜色
                        HOperatorSet.SetColor(hSmartWindowControls.HalconWindow, "green");
                        //设置文字
                        HOperatorSet.WriteString(hSmartWindowControls.HalconWindow, strs[i]);
                    }

                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 输出日志
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="time"></param>
        /// <param name="name"></param>
        /// <param name="result"></param>
        /// <param name="allTime"></param>
        public void ShowOk<T>(string time, string name, T[] result, string allTime)
        {
            try
            {
                if (result == null) return;
                string str = null;
                if (result is double[])
                {
                    foreach (var item in (result as double[]))
                    {
                        str += "[" + item.ToString("F3") + "]";
                    }

                }
                else
                {
                    foreach (var item in result)
                    {
                        str += "[" + item.ToString() + "]";
                    }
                }

           (FormDb.Db["Form1"] as Form1).textBox1.AppendText("当前时间：" + time + "     " + name + "运行成功 ！     执行时间:" + allTime + "ms     结果值：" + str + "\r\n");
            }
            catch
            {

            }
        }

        /// 右击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_MouseDown(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == MouseButtons.Right)
                {
                    mouseNode = treeView1.GetNodeAt(e.X, e.Y);
                    if (mouseNode != null && (mouseNode.Name.Contains("Int") || mouseNode.Name.Contains("Out") || mouseNode.Name.Contains("IntOrOut")))
                    {
                        //获取父节点
                        TreeNode fatherNode = mouseNode.Parent;
                        //获取父亲节点在treeview的下标
                        int index = treeView1.Nodes.IndexOf(fatherNode);
                        //获取右击菜单
                        ContextMenuStrip context = mouseNode.ContextMenuStrip;
                        //排除没有右击菜单的节点
                        if (context == null) return;
                        (context.Items[0] as ToolStripMenuItem).DropDownItems.Clear();
                        //排除根节点
                        if (index == 0) return;

                        //遍历此节点父节点上面所有节点 
                        for (int i = 0; i < index; i++)
                        {
                            //查找每个根节点下的所有子节点
                            TreeNodeCollection nodes = treeView1.Nodes[i].Nodes;
                            foreach (TreeNode item in nodes)
                            {
                                if (item.Name.Contains("Out"))
                                {
                                    //通过反射 获取当前遍历的节点（字段）
                                    FieldInfo itemInfo = item.Tag.GetType().GetField(item.Name);
                                    //通过反射 获取鼠标右击得到的节点（字段）
                                    FieldInfo mInFo = mouseNode.Tag.GetType().GetField(mouseNode.Name);
                                    //添加右击菜单  --这里我加了一下条件
                                    if (itemInfo.FieldType.Name == mInFo.FieldType.Name)
                                    {
                                        ToolStripMenuItem menuItem1 = new ToolStripMenuItem(treeView1.Nodes[i].Name + "." + item.Name);
                                        menuItem1.Tag = item.Tag;
                                        menuItem1.Click += MenuItem1_Click;
                                        (context.Items[0] as ToolStripMenuItem).DropDownItems.Add(menuItem1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 选择连接的输出节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                //之后写 本数据<=外部数据
                if (mouseNode != null && mouseNode.ForeColor != Color.Green)
                {
                    //先记录进来之间的节点名字
                    string text = mouseNode.Text;
                    mouseNode.Text = mouseNode.Text + "<—" + (sender as ToolStripMenuItem).Text;
                    mouseNode.ForeColor = Color.Green;
                    //在这里进行数据迭代 反射设置对应字段值
                    //获取所有字段--输出的
                    FieldInfo[] fieldsOut = (sender as ToolStripMenuItem).Tag.GetType().GetFields();
                    //获取所有字段--输入的
                    FieldInfo[] fieldsIn = mouseNode.Tag.GetType().GetFields();

                    object OutValue = null;
                    foreach (FieldInfo field in fieldsOut)
                    {
                        if (field.Name == (sender as ToolStripMenuItem).Text.Substring((sender as ToolStripMenuItem).Text.IndexOf('.') + 1))
                        {
                            OutValue = field.GetValue((sender as ToolStripMenuItem).Tag);
                            break;
                        }
                    }
                    //如果没有图像层则不让连接成功
                    if (OutValue == null) return;

                    foreach (FieldInfo field in fieldsIn)
                    {
                        if (text == field.Name)
                        {
                            field.SetValue(mouseNode.Tag, OutValue);
                            break;
                        }
                    }
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 鼠标出现在子节点上方时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        /// <summary>
        /// 显示原图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 原图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                foreach (TreeNode node in treeView1.Nodes)
                {
                    if (node.Text.Contains("相机工具"))
                    {
                        CamerForm camer = node.Tag as CamerForm;
                        //显示原图
                        if (camer.controller.HideOutputImage != null)
                        {
                            hSmartWindowControl1.HalconWindow.DispObj(camer.controller.HideOutputImage);
                        }
                    }
                }
            }
            catch
            {

            }
        }
        private void treeView1_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                TreeViewHitTestInfo hitTestInfo = treeView1.HitTest(e.Location);
                TreeNode node = hitTestInfo.Node;
                if (node == msMoveNode)
                {
                    return;
                }
                msMoveNode = node;
                if (node != null && (node.Name.Contains("Int") || node.Name.Contains("Out")))
                {
                    string str = "null";
                    //获取节点绑定tag对象
                    object controller = node.Tag;
                    FieldInfo field = node.Tag.GetType().GetField(hitTestInfo.Node.Name);
                    if (field.GetValue(controller) != null)
                    {
                        str = field.GetValue(controller).ToString();
                    }
                    if (str == "null")
                    {
                        str = field.FieldType.Name + "<Nothing>";
                    }
                    toolTip1.SetToolTip(treeView1, str);
                    // 假设你有一个方法来获取节点的额外信息  
                    toolTip1.SetToolTip(treeView1, str);
                }
                else
                {
                    toolTip1.SetToolTip(treeView1, string.Empty);
                }
            }
            catch
            {

            }
        }

        private void HwindowFlowNodeUrseControl_Load(object sender, EventArgs e)
        {
            try
            {
                string dataPathOK = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\NG\\";
                string dataPathNG = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\";
                if (!Directory.Exists(dataPathNG))
                {
                    Directory.CreateDirectory(dataPathNG);
                }
                if (!Directory.Exists(dataPathOK))
                {
                    Directory.CreateDirectory(dataPathOK);
                }
                string okFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\NG\\ng文件.txt";
                string ngFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\ok文件.txt";

                string ngCountFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\ng分析.dat";
                ngDictionary = HelpJsons.DeserializeKeyValuePairs(ngCountFilePath);
                this.Refresh();
                // 读取或创建 OK 文件
                okCount = ReadOrCreateFile(okFilePath);
                // 读取或创建 NG 文件
                ngCount = ReadOrCreateFile(ngFilePath);

                ContextMenuStrip contex = new ContextMenuStrip();
                //增加一个复制事件
                contex.Items.Add("粘贴节点", Image.FromFile("Data\\Image\\粘贴_paste.png"));
                contex.Items[0].Click += form1Controller.Form1Stickup_Click1;
                contex.Items[0].Tag = treeView1;

                treeView1.ContextMenuStrip = contex;
            }
            catch
            {
              //  MessageBox.Show("HwindowFlowNodeUrseControl_Load");
            }

        }
        private int ReadOrCreateFile(string filePath)
        {
            try
            {
                // 如果文件不存在，创建文件并写入默认值 0
                if (!File.Exists(filePath))
                {
                    File.WriteAllText(filePath, "0", Encoding.UTF8);
                    return 0;  // 返回默认值
                }
                // 如果文件存在，读取并返回值
                return int.Parse(File.ReadAllText(filePath, Encoding.UTF8));
            }
            catch
            {
                return 0;
            }
        }
        /// <summary>
        /// 保存图片按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            try
            {
                string path = $"Data\\训练图像\\";
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                HOperatorSet.DumpWindowImage(out HObject image, this.hSmartWindowControl1.HalconWindow);
                string fileName = path + DateTime.Now.ToString("yyyy年MM月dd日HH时mm分ss秒fff毫秒_即时保存图片");
                HOperatorSet.WriteImage(image, "png", 0, fileName);
                MessageBox.Show("保存成功", "提示");
            }
            catch
            {

            }
        }

        /// <summary>
        /// 重新开始计数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            try
            {
                string ngPath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\NG\\";
                string okPath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\";
                if (!Directory.Exists(ngPath))
                {
                    Directory.CreateDirectory(ngPath);
                }
                if (!Directory.Exists(okPath))
                {
                    Directory.CreateDirectory(okPath);
                }
                Directory.Delete(okPath, true);
                Directory.Delete(ngPath, true);

                Directory.CreateDirectory(okPath);
                Directory.CreateDirectory(ngPath);

                ngDictionary = new Dictionary<string, int>();
                customBarChartControl1.Data = ngDictionary;
                //这里还要清除饼状图计数NGOK率
                ngCount = 0;
                okCount = 0;
                using (StreamWriter writer = new StreamWriter(okPath + "ok文件.txt", append: false))
                {
                    writer.WriteLine("0");
                }
                using (StreamWriter writer = new StreamWriter(ngPath + "ng文件.txt", append: false))
                {
                    writer.WriteLine("0");
                }
                LabelMessage();
            }
            catch
            {

            }
        }

        // 使用线程安全的 ConcurrentQueue 替代 List<StringBuilder>
        private ConcurrentQueue<string> msQueue = new ConcurrentQueue<string>();
        //获取线程执行的数据
        public bool runPaper = true;
        /// <summary>
        /// 创建模板匹配的对象池
        /// </summary>
        private   ObjectPool<Shap_S_Matching> matcherPool = new ObjectPool<Shap_S_Matching>(40);
        /// <summary>
        /// 创建精准测量模块的对象池 一般3~5倍模板匹配 20*4或5 
        /// </summary>
        private  ObjectPool<CaliperModuleController> newModulePool = new ObjectPool<CaliperModuleController>(140);
        /// <summary>
        /// 创建临时窗体的对象池 一般模板匹配的1.2 
        /// </summary>
        private  ObjectPool<HSmartWindowControl> hSmartWindowControlPool = new ObjectPool<HSmartWindowControl>(60);
        /// <summary>
        /// 创建临时窗体的对象池 一般模板匹配的1.2 
        /// </summary>
        private  ObjectPool<Dictionary<List<bool>, string>> resultHelperPool = new ObjectPool<Dictionary<List<bool>, string>>(50);
        /// <summary>
        /// 创建多模块数据的对象池 一般模板匹配的1.5
        /// </summary>
        private  ObjectPool<ConcurrentDictionary<int, HardRunLine0>> threadDataPool = new ObjectPool<ConcurrentDictionary<int, HardRunLine0>>(50);
        /// <summary>
        /// 创建多模块线程的对象池 一般模板匹配的1.5
        /// </summary>
        private  ObjectPool<List<Task>> tasksPool = new ObjectPool<List<Task>>(50);

        /// <summary>
        /// 计时器对象池1 
        /// </summary>
        private  ObjectPool<Stopwatch> runTimePool = new ObjectPool<Stopwatch>(40);
        /// <summary>
        /// 计时器对象池1 
        /// </summary>
        private  ObjectPool<Stopwatch> stopwatchPool = new ObjectPool<Stopwatch>(40);
        /// <summary>
        /// 异步版本
        /// </summary>
        /// <param name="image"></param>
        public void HardTriggerRun(HObject image, int count)
        {
            if (treeView1.Nodes.Count < 2 || image == null) return;
            //全局计时
            Stopwatch runTime = runTimePool.Rent();
            runTime?.Start();
            //收集日志信息
            StringBuilder message = stringBuilderPool.Rent();
            //局部计时
            Stopwatch stopwatch = stopwatchPool.Rent();
            string noweDate = DateTime.Now.ToString("MM:dd:HH:mm:ss");

            HSmartWindowControl hSmartWindowControl = hSmartWindowControlPool.Rent();//窗体池拿出
            HOperatorSet.GetImageSize(image, out HTuple width, out HTuple height);
            hSmartWindowControl.Size = new Size(width, height);
            HOperatorSet.DispObj(image, hSmartWindowControl.HalconWindow);
            hSmartWindowControl.SetFullImagePart();

            //多目标模板匹配窗体
            H_PMA_S_AlignToolForm pmaForm = (treeView1.Nodes[1].Tag as H_PMA_S_AlignToolForm);
            Shap_S_Matching pmaController = pmaForm.controller;

            if (treeView1.Nodes[1].ForeColor == Color.Red)
            {
                treeView1.Nodes[1].ForeColor = Color.Black;
            }
            //执行模板匹配 获取模板的数据
            double[] HideOutputArrayRows = new double[0];
            double[] HideOutputArrayColumns = new double[0];
            double[] HideOutputArrayPhis = new double[0];
            //模板匹配模块
            Shap_S_Matching matcher = matcherPool.Rent();//模板对象池拿出
            try
            {
                if (runPaper)
                {
                    message?.Append($"当前工位：{this.name} 运行次数：{count} \r\n");
                    stopwatch.Start();
                    matcher.HardRun(image, pmaForm.filePath, pmaForm, pmaController.searchArea, hSmartWindowControl, ref HideOutputArrayRows, ref HideOutputArrayColumns, ref HideOutputArrayPhis);
                    double[] HideOutputArrayScores = matcher.HideOutputArrayScores;
                    stopwatch.Stop();
                    message?.Append(ShowMessage<double>(noweDate, treeView1.Nodes[1].Name, HideOutputArrayScores, stopwatch.ElapsedMilliseconds.ToString()));
                    Interlocked.Exchange(ref pmaController.HideIntputImage, image);
                    Interlocked.Exchange(ref pmaController.HideOutputArrayRows, HideOutputArrayRows);
                    Interlocked.Exchange(ref pmaController.HideOutputArrayColumns, HideOutputArrayColumns);
                    Interlocked.Exchange(ref pmaController.HideOutputArrayPhis, HideOutputArrayPhis);
                }else
                {
                    image.DispObj(hSmartWindowControl.HalconWindow);
                    hSmartWindowControlPool.Return(hSmartWindowControl);
                    stringBuilderPool.Return(message);
                    runTimePool.Return(runTime);
                    stopwatchPool.Return(stopwatch);
                }
            }
            catch (Exception ex)
            {
                if (runPaper)
                {
                    runPaper = false;
                    //展示ng画面
                    HOperatorSet.DumpWindowImage(out HObject nImage, hSmartWindowControl.HalconWindow);
                    HOperatorSet.DispObj(nImage, hSmartWindowControl1.HalconWindow);
                    hSmartWindowControl1.SetFullImagePart();
                    ShowNgForm(nImage);
                    WriteImage(nImage, false, treeView1.Nodes[1].Name);
                    //同步一下日志
                    message.Append(pmaForm.Name.ToString() + "出错！！！\r\n");
                    string newText = string.Join(Environment.NewLine, message.ToString());
                    msQueue.Enqueue(newText);
                    UpdateTextBox();
                    //同步一下label
                    LabelMessage();

                    if (treeView1.Nodes.Count > 0)//判断当前工位有没有相机工具
                    {
                        camerFormController = (treeView1.Nodes[0].Tag as CamerForm).controller;
                    }
                    if (camerFormController != null)
                    {
                        camerFormController.LevelReversal();//输出电平信号
                    }
                    if (treeView1.Nodes.Count > 0)//判断当前工位有没有相机工具
                    {
                        camerFormController = (treeView1.Nodes[0].Tag as CamerForm).controller;
                    }
                    if (camerFormController != null)
                    {
                        camerFormController.LevelReversal();//输出电平信号
                    }
                }
                image.DispObj(hSmartWindowControl.HalconWindow);
                hSmartWindowControlPool.Return(hSmartWindowControl);
                stringBuilderPool.Return(message);
                runTimePool.Return(runTime);
                stopwatchPool.Return(stopwatch);
            }
            finally
            {
                matcherPool.Return(matcher);// 归还对象池
            }
            
            List<Task> tasks = tasksPool.Rent();
            //结果分析工具帮助集合 获取对象池对象
            Dictionary<List<bool>, string> resultHelper = resultHelperPool.Rent();

            ConcurrentDictionary<int, HardRunLine0> threadData = threadDataPool.Rent();
            //执行其他节点
            for (int j = 2; j < treeView1.Nodes.Count; j++)
            {
                int i = j;
                TreeNode item = treeView1.Nodes[j];

                if (item.Text.Contains("测量模块") && runPaper)
                {
                    tasks.Add(Task.Run(() =>
                    {
                        HardRunLine0 values = new HardRunLine0();
                        threadData.TryAdd(i, values);
                        //创建局部变量
                        CaliperModuleController newModule= newModulePool.Rent();//模块池回收
                        try
                        {
                            if (runPaper==false)
                            {
                                newModulePool.Return(newModule);
                                image.DispObj(hSmartWindowControl.HalconWindow);
                                hSmartWindowControlPool.Return(hSmartWindowControl);
                                stringBuilderPool.Return(message);
                                resultHelperPool.Return(resultHelper);
                                threadDataPool.Return(threadData);
                                tasksPool.Return(tasks);
                                runTimePool.Return(runTime);
                                stopwatchPool.Return(stopwatch);
                            }

                            if (threadData.TryGetValue(i, out var data))
                            {

                                //获取精准测量模块窗体数据
                                CaliperModuleForm cmoduleForm = (treeView1.Nodes[i].Tag as CaliperModuleForm);
                                //获取算子对象
                                CaliperModuleController modelController = cmoduleForm.controller;
                                stopwatch?.Start();
                                //卡尺工具运行
                                newModule.HardRunCailper(hSmartWindowControl, image, HideOutputArrayRows, HideOutputArrayPhis, HideOutputArrayColumns, cmoduleForm.caliperForm, cmoduleForm.caliperForm.controller.strdb, double.Parse(cmoduleForm.caliperForm.numericUpDown9.Value.ToString()), double.Parse(cmoduleForm.caliperForm.numericUpDown8.Value.ToString()), ref threadData[i].linesList, ref threadData[i].HideOutputArrayDistancesCailper, ref threadData[i].HideOutputArrayRowsCailper, ref threadData[i].HideOutputArrayColumnsCailper, cmoduleForm.caliperForm.controller.line1Place, cmoduleForm.caliperForm.controller.line2Place, cmoduleForm.caliperForm.controller.line1counterFrist, cmoduleForm.caliperForm.controller.line2counterFrist);
                                //距离转换运行
                                newModule.HardRunDistance(cmoduleForm.distanceForm, threadData[i].HideOutputArrayDistancesCailper, ref threadData[i].HideOutputArrayDistancesDistance);
                                //结果分析运行
                                if (cmoduleForm.analyseForm.comboBox1.Text == "打开")
                                {
                                    List<double> anal = new List<double>();
                                    anal.AddRange(threadData[i].HideOutputArrayDistancesDistance);
                                    newModule.HardRunAnalyse(cmoduleForm.analyseForm, anal, ref threadData[i].HideOutputResultsAna);
                                    resultHelper?.Add(threadData[i].HideOutputResultsAna, treeView1.Nodes[i].Name);
                                }
                                //文本显示运行
                                if (cmoduleForm.messageForm.comboBox4.Text == "打开")
                                {
                                    Console.WriteLine("进入： " + Task.CurrentId);
                                    newModule.HardRunMessage(cmoduleForm.messageForm, threadData[i].HideOutputArrayRowsCailper, threadData[i].HideOutputArrayColumnsCailper, hSmartWindowControl, threadData[i].HideOutputArrayDistancesDistance, threadData[i].HideOutputResultsAna);
                                }
                                //间距测量分析
                                if (cmoduleForm.distansceForm.comboBox1.Text == "打开")
                                {
                                    DistanceForm distansceForm = cmoduleForm.distansceForm;
                                    newModule.HardRunDistanceS();
                                }
                                stopwatch?.Stop();
                                message?.Append(ShowMessage<double>(noweDate, treeView1.Nodes[i].Name, threadData[i].HideOutputArrayDistancesDistance, stopwatch?.ElapsedMilliseconds.ToString()));

                                item.ForeColor = Color.Black;
                                //给卡尺窗体赋值
                                Interlocked.Exchange(ref cmoduleForm.caliperForm.controller.HideIntputImage, image);
                                Interlocked.Exchange(ref cmoduleForm.caliperForm.controller.HideIntputArrayRows, HideOutputArrayRows);
                                Interlocked.Exchange(ref cmoduleForm.caliperForm.controller.HideIntputArrayPhis, HideOutputArrayPhis);
                                Interlocked.Exchange(ref cmoduleForm.caliperForm.controller.HideIntputArrayColumns, HideOutputArrayColumns);
                                Interlocked.Exchange(ref cmoduleForm.caliperForm.controller.HideOutputArrayDistances, threadData[i].HideOutputArrayDistancesDistance);
                                //给距离转换窗体赋值
                                Interlocked.Exchange(ref cmoduleForm.distanceForm.controller.HideIntputArrayDistances, threadData[i].HideOutputArrayDistancesCailper);
                                Interlocked.Exchange(ref cmoduleForm.distanceForm.controller.HideOutputArrayDistances, threadData[i].HideOutputArrayDistancesDistance);
                            }

                        }
                        catch (Exception ex)
                        {
                            if (runPaper)
                            {
                                runPaper = false;
                                if (treeView1.Nodes.Count > 0)//判断当前工位有没有相机工具
                                {
                                    camerFormController = (treeView1.Nodes[0].Tag as CamerForm).controller;
                                }
                                if (camerFormController != null)
                                {
                                    camerFormController.LevelReversal();//输出电平信号
                                }
                                
                                item.ForeColor = Color.Red;
                                //展示ng画面
                                HOperatorSet.DumpWindowImage(out HObject nImage, hSmartWindowControl.HalconWindow);
                                HOperatorSet.DispObj(nImage, hSmartWindowControl1.HalconWindow);
                                hSmartWindowControl1.SetFullImagePart();
                                //输出ng信息
                                ShowNgForm(nImage);
                                WriteImage(nImage, false, item.Text.ToString());
                                //同步一下日志
                                message.Append(item.Name.ToString() + "出错！！！\r\n");
                                string newText = string.Join(Environment.NewLine, message.ToString());
                                msQueue.Enqueue(newText);
                                UpdateTextBox();
                                //同步一下label
                                LabelMessage();
                            }
                            image.DispObj(hSmartWindowControl.HalconWindow);
                            hSmartWindowControlPool.Return(hSmartWindowControl);
                            stringBuilderPool.Return(message);
                            resultHelperPool.Return(resultHelper);
                            threadDataPool.Return(threadData);
                            tasksPool.Return(tasks);
                            runTimePool.Return(runTime);
                            stopwatchPool.Return(stopwatch);
                        }
                        finally
                        {
                            newModulePool.Return(newModule);
                        }
                    }));
                }
            }
            // 等待所有任务完成

            for (int i = 0; i < tasks.Count; i++)
            {
                tasks[i].Wait();
            }
            runTime?.Stop();
            if (runPaper)
            {
                try
                {
                    HOperatorSet.DumpWindowImage(out HObject nImage, hSmartWindowControl.HalconWindow);
                    //分析工具
                    ToolAnalysis(resultHelper, nImage);
                    (treeView1.Nodes[0].Tag as CamerForm).controller.HideOutputImage = image;

                    ShowResults(new string[] { "运行时间：" + runTime.ElapsedMilliseconds + " ms", "ok数：" + okCount, "ng数：" + ngCount, "ok率：" + (okCount / (ngCount + okCount) * 100) + "%" }, hSmartWindowControl);
                }
                catch (Exception ex)
                {
                    if (ex.Message.Contains("未将对象") || ex.Message.Contains("尝试除以"))
                    {
                        runPaper = true;
                    }
                    else
                    {
                        if (treeView1.Nodes.Count > 0)//判断当前工位有没有相机工具
                        {
                            camerFormController = (treeView1.Nodes[0].Tag as CamerForm).controller;
                        }
                        if (camerFormController != null)
                        {
                            camerFormController.LevelReversal();//输出电平信号
                        }
                        runPaper = false;
                    }
                }
                finally
                {
                    HOperatorSet.DumpWindowImage(out HObject nImage, hSmartWindowControl.HalconWindow);
                    if (hSmartWindowControl.HalconWindow != null || hSmartWindowControl1.HalconWindow != null)
                    {
                        if (Interlocked.Exchange(ref _isRendering, 1) == 0)
                        {
                            try
                            {
                                string newText = string.Join(Environment.NewLine, message.ToString());
                                msQueue.Enqueue(newText);
                                HOperatorSet.DispObj(nImage, hSmartWindowControl1.HalconWindow);
                                hSmartWindowControl1.SetFullImagePart();
                                //实时监控图像
                                if (framesTimeForm != null)
                                {
                                    HOperatorSet.DispObj(nImage, framesTimeForm.Hwindow.HalconWindow);
                                    framesTimeForm.Hwindow.SetFullImagePart();
                                }
                            }
                            finally
                            {
                                // 渲染完成后释放锁
                                Interlocked.Exchange(ref _isRendering, 0);
                            }
                        }

                    }
                    image.DispObj(hSmartWindowControl.HalconWindow);
                    nImage?.Dispose();
                    hSmartWindowControlPool.Return(hSmartWindowControl);
                    stringBuilderPool.Return(message);
                    resultHelperPool.Return(resultHelper);
                    threadDataPool.Return(threadData);
                    tasksPool.Return(tasks);
                    runTimePool.Return(runTime);
                    stopwatchPool.Return(stopwatch);
                }
            }else
            {
                image.DispObj(hSmartWindowControl.HalconWindow);
                hSmartWindowControlPool.Return(hSmartWindowControl);
                stringBuilderPool.Return(message);
                resultHelperPool.Return(resultHelper);
                threadDataPool.Return(threadData);
                tasksPool.Return(tasks);
                runTimePool.Return(runTime);
                stopwatchPool.Return(stopwatch);
            }
        }
        // 用于标识是否有线程正在渲染图像
        private int _isRendering = 0;

        /// <summary>
        /// 输出日志
        /// </summary>
        /// <typeparam name="T">结果数组的元素类型</typeparam>
        /// <param name="time">当前时间</param>
        /// <param name="name">名称</param>
        /// <param name="result">结果数组</param>
        /// <param name="allTime">执行时间</param>
        /// <returns>格式化的日志信息</returns>
        public string ShowMessage<T>(string time, string name, T[] result, string allTime)
        {
            try
            {
                if (result == null || result.Length == 0) return null;

                // 使用 StringBuilder 构建结果字符串
                var strBuilder = new StringBuilder();
                foreach (var item in result)
                {
                    if (item is double value)
                    {
                        strBuilder.AppendFormat("[{0:F3}]", value);
                    }
                    else
                    {
                        strBuilder.AppendFormat("[{0}]", item);
                    }
                }

                // 返回格式化的日志信息
                return $"当前时间：{time}     {name}运行成功！     执行时间：{allTime}ms     结果值：{strBuilder}\r\n";
            }
            catch
            {
                return null ;
            }
        }

        /// <summary>
        /// 置为按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void toolStripButton4_Click(object sender, EventArgs e)
        {
            try
            {
               // MessageBox.Show("置位成功");
                runPaper = true;
                timer2.Enabled = true;
                timer3.Enabled = true;
                timer4.Enabled = true;
                timer5.Enabled = true;
                if (camerFormController != null)
                {
                    if (camerFormController.triggerSourcePaper && camerFormController.triggerModePaper)
                    {
                        framesTimeForm.indicatorLight1.State = IndicatorLight.IndicatorState.GreenStable; // 切换为绿色稳定
                    }
                }
            }
            catch
            {
               // MessageBox.Show("toolStripButton4_Click");
            }
        }
        #region 更新label数据
        // 是否正在进行更新
        private bool isUpdating = false;
        /// <summary>
        /// 更新结果分析
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void timer2_Tick(object sender, EventArgs e)
        {
            try
            {
                if (!runPaper)
                {
                    (sender as System.Windows.Forms.Timer).Enabled = false;
                    return;
                }
                else
                {
                    LabelMessage();
                }
            }
            catch
            {
                //MessageBox.Show("timer2_Tick");
            }
        }
        public double antherCount;
        /// <summary>
        /// 更新ng，ok个数以及百分比
        /// </summary>
        public async void LabelMessage()
        {
            if (isUpdating) return;
            try
            {
                // 局部变量，避免多次访问全局变量
                int localOkCount = okCount;
                int localNgCount = ngCount;

                // 计算数据（示例，替换为实际逻辑）
                double totalCount = localOkCount + localNgCount;
                //避免无意义的数据刷新
                if (totalCount == antherCount) return;
                antherCount = totalCount;

                double okPercentage = totalCount == 0 ? 0 : (double)localOkCount / totalCount * 100;
                double ngPercentage = 100 - okPercentage;

                // 异步执行UI更新，避免阻塞UI线程
                await Task.Run(() =>
                {
                    // 确保UI更新发生在主线程
                    Invoke(new Action(() =>
                     {
                         // 更新所有标签
                         UpdateLabelTextIfChanged(framesTimeForm.sumLabel, totalCount.ToString());
                         UpdateLabelTextIfChanged(framesTimeForm.okLabel, localOkCount.ToString());
                         UpdateLabelTextIfChanged(framesTimeForm.ngLabel, localNgCount.ToString());
                         UpdateLabelTextIfChanged(framesTimeForm.okLabelRate, okPercentage.ToString("F3") + "%");
                         UpdateLabelTextIfChanged(framesTimeForm.ngLabelRate, ngPercentage.ToString("F3") + "%");

                         // 更新主窗口的标签
                         UpdateLabelTextIfChanged(sum, totalCount.ToString());
                         UpdateLabelTextIfChanged(okLabel, localOkCount.ToString());
                         UpdateLabelTextIfChanged(oksum, okPercentage.ToString("F3") + "%");
                         UpdateLabelTextIfChanged(nGLabel, localNgCount.ToString());
                         UpdateLabelTextIfChanged(nGsum, ngPercentage.ToString("F3") + "%");
                     }));
                });
            }
            catch (Exception ex)
            {
                //MessageBox.Show("LabelMessage");
            }
        }
        /// <summary>
        /// 更新label文本值，如果新值与当前值不同，则更新
        /// </summary>
        /// <param name="label">需要更新的label控件</param>
        /// <param name="newText">新的文本值</param>
        public void UpdateLabelTextIfChanged(System.Windows.Forms.Label label, string newText)
        {
            try
            {
                if (label.Text != newText)
                {
                    UpdateLabelText(label, newText);
                }
            }
            catch
            {
               // MessageBox.Show("UpdateLabelTextIfChanged");
            }
        }
        /// <summary>
        /// 更新label
        /// </summary>
        /// <param name="label">需要更新的label控件</param>
        /// <param name="newText">新的文本值</param>
        public void UpdateLabelText(System.Windows.Forms.Label label, string newText)
        {
            try
            {
                if (label.InvokeRequired)
                {
                    label.Invoke(new Action<System.Windows.Forms.Label, string>(UpdateLabelText), label, newText);
                }
                else
                {
                    // 更新label文本值
                    label.Text = newText;
                }
            }
            catch
            {
                //MessageBox.Show("UpdateLabelText");
            }
        }
        #endregion  
        #region 定时垃圾回收
        /// <summary>
        /// 定时启动垃圾回收
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static long lastGcMemory = 0;
        private static long gcThreshold = 1024 * 1024 * 100;  // 100MB 阈值
        private static long gcChangeThreshold = 1024 * 1024 * 20;  // 内存变化阈值，20MB
        private static DateTime lastGcTime = DateTime.MinValue;  // 上次垃圾回收时间
        private static TimeSpan gcCooldownTime = TimeSpan.FromSeconds(10);  // 冷却时间
        private void timer4_Tick(object sender, EventArgs e)
        {
            try
            {
                // 获取当前总内存使用量
                long currentMemory = GC.GetTotalMemory(false);

                // 判断内存使用是否超过了阈值，并且变化量是否超过设定的阈值
                if (currentMemory > gcThreshold && (currentMemory - lastGcMemory) > gcChangeThreshold)
                {
                    // 只有当冷却时间已过，才触发垃圾回收
                    if (DateTime.Now - lastGcTime > gcCooldownTime)
                    {
                        // 执行垃圾回收
                        GC.Collect();
                        lastGcMemory = currentMemory;  // 更新上次垃圾回收时的内存使用量
                        lastGcTime = DateTime.Now;  // 更新回收时间
                    }
                }
            }
            catch (Exception ex)
            {
                // 错误处理，避免未捕获的异常导致程序崩溃
               // MessageBox.Show("timer4_Tick error: " + ex.Message);
            }
        }
        #endregion
        #region 日志方面的代码(写入textbox1与写入日志文件
        // 用于缓存日志内容的队列
        private readonly ConcurrentQueue<string> _logQueue = new ConcurrentQueue<string>();
        private bool _isUpdatingTextBox = false; // 标志位，用于避免多次并发更新 textBox1
        private static ObjectPool<StringBuilder> stringBuilderPool = new ObjectPool<StringBuilder>(50);
        /// <summary>
        /// timer3 - 每1.5秒执行一次，处理队列内容写入 TextBox
        /// </summary>
        private async void timer3_Tick(object sender, EventArgs e)
        {
            if (!runPaper)
            {
                (sender as System.Windows.Forms.Timer).Enabled = false;
                return;
            }

            // 异步处理队列，避免阻塞 UI
            await Task.Run(() =>
            {
                try
                {
                    UpdateTextBox();
                }
                catch
                {
                    //MessageBox.Show("timer3_Tick");
                }
            });
        }
        public void UpdateTextBox()
        {
            try
            {
                List<StringBuilder> newContent = new List<StringBuilder>();
                while (msQueue.TryDequeue(out var item))
                {
                    // 从对象池获取 StringBuilder
                    var sb = stringBuilderPool.Rent();
                    sb.Append(item); // 使用 StringBuilder 进行拼接
                    newContent.Add(sb); // 添加到结果列表
                }

                if (newContent.Count > 0)
                {
                    string newText = string.Join(Environment.NewLine, newContent.Select(sb => sb.ToString()));
                    _logQueue.Enqueue(newText); // 将内容重新放入队列用于 UI 更新

                    // 归还 StringBuilder 到对象池
                    foreach (var sb in newContent)
                    {
                        stringBuilderPool.Return(sb); // 将使用过的 StringBuilder 归还
                    }
                }
                // 更新 UI，避免阻塞
                UpdateTextBoxAsync();
            }
            catch
            {
                //MessageBox.Show("timer3_Tick");
            }
        }
        /// <summary>
        /// 异步更新 TextBox 内容
        /// </summary>
        private async void UpdateTextBoxAsync(bool clearTextBox = false)
        {
            if (_isUpdatingTextBox) return; // 如果已经在更新，则直接返回
            _isUpdatingTextBox = true;

            await Task.Run(() =>
            {
                (FormDb.Db["Form1"] as Form1)?.Invoke(new Action(() =>
                {
                    try
                    {
                        var form1 = (FormDb.Db["Form1"] as Form1);
                        if (form1?.textBox1 != null)
                        {
                            if (clearTextBox)
                            {
                                form1.textBox1.Clear();
                            }
                            else
                            {
                                while (_logQueue.TryDequeue(out string logItem))
                                {
                                    form1.textBox1.AppendText(logItem + Environment.NewLine);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        //MessageBox.Show("UpdateTextBoxAsync");
                    }
                    finally
                    {
                        _isUpdatingTextBox = false; // 标志位重置
                    }
                }));
            });
        }

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void timer5_Tick(object sender, EventArgs e)
        {
            if (!runPaper)
            {
                (sender as System.Windows.Forms.Timer).Enabled = false;
                return;
            }
            // 异步写入日志文件
            await Task.Run(() =>
            {
                try
                {
                    string okFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\NG\\ng文件.txt";
                    string ngFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\ok文件.txt";

                    File.WriteAllText(okFilePath, okCount.ToString());
                    File.WriteAllText(ngFilePath, ngCount.ToString());

                    // 收集所有日志内容写入文件
                    List<string> logContent = new List<string>();
                    while (_logQueue.TryDequeue(out string logItem))
                    {
                        logContent.Add(logItem);
                    }

                    if (logContent.Count > 0)
                    {
                        Form1.log?.Error(string.Join(Environment.NewLine, logContent));
                    }
                }
                catch (Exception ex)
                {
                   // MessageBox.Show("timer5_Tick");
                }
            });

            // 清空 TextBox 的内容
            UpdateTextBoxAsync(clearTextBox: true);
        }
        #endregion

        public void FormClosing()
        {
            try
            {
                List<string> newContent = new List<string>();
                while (msQueue.TryDequeue(out var item))
                {
                    newContent.Add(item);
                }

                if (newContent.Count > 0)
                {
                    string newText = string.Join(Environment.NewLine, newContent);
                    _logQueue.Enqueue(newText); // 将内容重新放入队列用于 UI 更新
                }


                string okFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\NG\\ng文件.txt";
                string ngFilePath = $"Data\\工程文件\\{this.projectName}\\{this.name}任务文件\\OKNG图片\\OK\\ok文件.txt";

                File.WriteAllText(okFilePath, okCount.ToString());
                File.WriteAllText(ngFilePath, ngCount.ToString());

                // 收集所有日志内容写入文件
                List<string> logContent = new List<string>();
                while (_logQueue.TryDequeue(out string logItem))
                {
                    logContent.Add(logItem);
                }

                if (logContent.Count > 0)
                {
                    Form1.log?.Error(string.Join(Environment.NewLine, logContent));
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show("timer5_Tick");
            }
        }
        public double mouse_col = 0;
        public double mouse_row = 0;
        public MouseButtons button;

        private void hSmartWindowControl1_HMouseMove(object sender, HMouseEventArgs e)
        {
            try
            {
                mouse_col = e.X;
                mouse_row = e.Y;
                button = e.Button;
            }
            catch
            {
               // MessageBox.Show("hSmartWindowControl1_HMouseMove");
            }
        }
        /// <summary>
        /// 测试—自动检测置位—30s检测一次
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer测试_Tick(object sender, EventArgs e)
        {
            if (runPaper == false)
            {
                toolStripButton4_Click(this, e);
            }
        }
    }
    public delegate void UpdateLogDelegate();
    public delegate void UpdateTextBoxDelegate(string text);
    /// <summary>
    /// 精准测量模块局部测量数据
    /// </summary>
    public class HardRunLine0
    {
        //卡尺工具数据
        public double[,] linesList;
        public double[] HideOutputArrayDistancesCailper;
        public double[] HideOutputArrayRowsCailper;
        public double[] HideOutputArrayColumnsCailper;
        //距离转换数据
        public double[] HideOutputArrayDistancesDistance;
        //结果分析数据
        public List<bool> HideOutputResultsAna;
    }
    public class ObjectPool<T> where T : class, new()
    {
        private readonly ConcurrentBag<T> _pool;
        private readonly int _maxPoolSize;

        public ObjectPool(int maxPoolSize = 50)
        {
            _pool = new ConcurrentBag<T>();
            _maxPoolSize = maxPoolSize;
        }

        // 获取对象
        public T Rent()
        {
            // 如果池中有对象，直接返回
            if (_pool.TryTake(out var item))
            {
                return item;
            }

            // 如果池为空，创建新对象
            return new T();
        }

        // 归还对象
        public void Return(T item)
        {
            if (item == null) return;
            // 清理对象的数据
            ClearItemData(item);

            // 如果池未超出容量，将对象放回池中
            if (_pool.Count < _maxPoolSize)
            {
                _pool.Add(item);
            }else if (item is HSmartWindowControl hSmart)
            {
                hSmart.Dispose();
            }
            // 如果超出容量，丢弃对象（让 GC 回收）
        }

        // 清理对象的数据
        private void ClearItemData(T item)
        {
            if (item is StringBuilder sb)
            {
                sb.Clear(); 
            }
            else if (item is Dictionary<List<bool>, string> list)
            {
                list.Clear();  
            }
            else if (item is List<Task> dictionary)
            {
                dictionary.Clear();  
            }else if (item is HSmartWindowControl hsmart)
            {
                hsmart.HalconWindow.ClearWindow();
                hsmart.HalconWindow.SetPart(0, 0, hsmart.Height - 1, hsmart.Width - 1);
                hsmart.HalconWindow.DispText("", "image", 0, 0, "black", "box", "false");

            }
            else if (item is ConcurrentDictionary<int, HardRunLine0> hList)
            {
                hList.Clear();
            }else if (item is Stopwatch stop)
            {
                stop.Reset();
            }
            // 添加其他类型的数据清理逻辑
        }
    }
}
